// VGameEngine Core Minimal Header

#pragma once
// Simple Library核心组件
#include "qtypes.h"
#include "simple_library.h"

// 内联宏定义
#ifdef _MSC_VER
    #define VG_FORCE_INLINE __forceinline
    #define VG_NO_INLINE __declspec(noinline)
#elif defined(__GNUC__) || defined(__clang__)
    #define VG_FORCE_INLINE inline __attribute__((always_inline))
    #define VG_NO_INLINE __attribute__((noinline))
#else
    #define VG_FORCE_INLINE inline
    #define VG_NO_INLINE
#endif

// 对齐宏定义
#ifdef _MSC_VER
    #define VG_ALIGN(n) __declspec(align(n))
#elif defined(__GNUC__) || defined(__clang__)
    #define VG_ALIGN(n) __attribute__((aligned(n)))
#else
    #define VG_ALIGN(n)
#endif

// 弃用警告宏
#ifdef _MSC_VER
    #define VG_DEPRECATED __declspec(deprecated)
    #define VG_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
#elif defined(__GNUC__) || defined(__clang__)
    #define VG_DEPRECATED __attribute__((deprecated))
    #define VG_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
#else
    #define VG_DEPRECATED
    #define VG_DEPRECATED_MSG(msg)
#endif

// 导出/导入宏
#ifdef _WIN32
    #define VG_EXPORT __declspec(dllexport)
    #define VG_IMPORT __declspec(dllimport)
#else
    #define VG_EXPORT __attribute__((visibility("default")))
    #define VG_IMPORT
#endif

// 函数调用约定
#ifdef _WIN32
    #define VG_CDECL __cdecl
    #define VG_STDCALL __stdcall
    #define VG_FASTCALL __fastcall
#else
    #define VG_CDECL
    #define VG_STDCALL
    #define VG_FASTCALL
#endif

/*----------------------------------------------------------------------------
    VGameEngine核心宏定义
----------------------------------------------------------------------------*/

// VGameEngine日志级别枚举 - 基于UE5的ELogVerbosity设计
namespace VGLogVerbosity
{
    enum Type : quint8
    {
        NoLogging = 0,    // 不记录日志
        Fatal,            // 致命错误，会导致程序崩溃
        Error,            // 错误，影响功能但不崩溃
        Warning,          // 警告，潜在问题
        Display,          // 重要信息，显示到控制台
        Log,              // 一般日志，只写入文件
        Verbose,          // 详细日志
        VeryVerbose,      // 非常详细的日志
        
        All = VeryVerbose,
        NumVerbosity,
        VerbosityMask = 0xF
    };
}

// 日志类别名称类型 - 使用简单的const char*替代UE5的FName
using VGLogCategoryName = const char*;

// 日志类别基类 - 完全按照UE5的FLogCategoryBase设计
struct VGLogCategoryBase
{
    /**
     * 构造函数，设置默认值
     *
     * @param CategoryName           类别名称
     * @param DefaultVerbosity       运行时默认详细程度
     * @param CompileTimeVerbosity   编译时详细程度
     */
    VGLogCategoryBase(const VGLogCategoryName& CategoryName, VGLogVerbosity::Type DefaultVerbosity, VGLogVerbosity::Type CompileTimeVerbosity);

    /** 测试运行时详细程度，判断是否应该抑制日志输出 */
    VG_FORCE_INLINE constexpr bool IsSuppressed(VGLogVerbosity::Type VerbosityLevel) const
    {
        return !((VerbosityLevel & VGLogVerbosity::VerbosityMask) <= Verbosity);
    }

    /** 获取类别名称 */
    inline constexpr const VGLogCategoryName& GetCategoryName() const { return CategoryName; }

    /** 获取工作详细程度 */
    inline constexpr VGLogVerbosity::Type GetVerbosity() const { return (VGLogVerbosity::Type)Verbosity; }
    
    /** 设置工作详细程度并限制到编译时详细程度 */
    void SetVerbosity(VGLogVerbosity::Type Verbosity);

    /** 获取编译时详细程度 */
    inline constexpr VGLogVerbosity::Type GetCompileTimeVerbosity() const { return CompileTimeVerbosity; }

private:
    /** 当前抑制状态 */
    VGLogVerbosity::Type Verbosity;
    /** 默认抑制 */
    quint8 DefaultVerbosity:1;
    /** 编译时抑制 */
    const VGLogVerbosity::Type CompileTimeVerbosity;
    /** 此类别的名称 */
    const VGLogCategoryName CategoryName;
};

/** 模板日志类别，将编译时常量默认值和编译时详细程度传递给VGLogCategoryBase构造函数 */
template <VGLogVerbosity::Type InDefaultVerbosity, VGLogVerbosity::Type InCompileTimeVerbosity>
struct VGLogCategory : public VGLogCategoryBase
{
    static_assert((InDefaultVerbosity & VGLogVerbosity::VerbosityMask) < VGLogVerbosity::NumVerbosity, "Bogus default verbosity.");
    static_assert(InCompileTimeVerbosity < VGLogVerbosity::NumVerbosity, "Bogus compile time verbosity.");

    static constexpr VGLogVerbosity::Type CompileTimeVerbosity = InCompileTimeVerbosity;

    inline constexpr VGLogVerbosity::Type GetCompileTimeVerbosity() const { return CompileTimeVerbosity; }

    VG_FORCE_INLINE VGLogCategory(const VGLogCategoryName& InCategoryName)
        : VGLogCategoryBase(InCategoryName, InDefaultVerbosity, CompileTimeVerbosity)
    {
    }
};

// 日志输出函数 - 内联实现
inline void VGLogOutput(const VGLogCategoryName& CategoryName, VGLogVerbosity::Type Verbosity, const char* Format, ...)
{
    va_list args;
    va_start(args, Format);
    
    // 创建格式化的消息
    char buffer[1024];
    vsnprintf(buffer, sizeof(buffer), Format, args);
    
    // 根据日志级别调用simple_library的对应函数
    switch (Verbosity & VGLogVerbosity::VerbosityMask)
    {
        case VGLogVerbosity::Fatal:
        case VGLogVerbosity::Error:
            log_error("[%s] %s", CategoryName, buffer);
            break;
        case VGLogVerbosity::Warning:
            log_warning("[%s] %s", CategoryName, buffer);
            break;
        case VGLogVerbosity::Display:
        case VGLogVerbosity::Log:
            log_log("[%s] %s", CategoryName, buffer);
            break;
        case VGLogVerbosity::Verbose:
        case VGLogVerbosity::VeryVerbose:
            log_success("[%s] %s", CategoryName, buffer);
            break;
        default:
            log_log("[%s] %s", CategoryName, buffer);
            break;
    }
    
    va_end(args);
}

// VGLogCategoryBase构造函数 - 内联实现
inline VGLogCategoryBase::VGLogCategoryBase(const VGLogCategoryName& CategoryName, VGLogVerbosity::Type DefaultVerbosity, VGLogVerbosity::Type CompileTimeVerbosity)
    : Verbosity(DefaultVerbosity)
    , DefaultVerbosity(static_cast<quint8>(DefaultVerbosity))
    , CompileTimeVerbosity(CompileTimeVerbosity)
    , CategoryName(CategoryName)
{
}

// VGLogCategoryBase::SetVerbosity - 内联实现
inline void VGLogCategoryBase::SetVerbosity(VGLogVerbosity::Type InVerbosity)
{
    Verbosity = (InVerbosity & VGLogVerbosity::VerbosityMask) <= CompileTimeVerbosity ? InVerbosity : CompileTimeVerbosity;
}

/** 
 * 在头文件中声明日志类别为C++ "extern"，通常与源文件中的DEFINE_LOG_CATEGORY配对使用。
 * 包含头文件的所有文件都可以访问。
 * @param CategoryName, 要声明的类别
 * @param DefaultVerbosity, 默认运行时详细程度
 * @param CompileTimeVerbosity, 编译到代码中的最大详细程度
 **/
#define DECLARE_LOG_CATEGORY_EXTERN(CategoryName, DefaultVerbosity, CompileTimeVerbosity) \
    extern struct VGLogCategory##CategoryName : public VGLogCategory<VGLogVerbosity::DefaultVerbosity, VGLogVerbosity::CompileTimeVerbosity> \
    { \
        VG_FORCE_INLINE VGLogCategory##CategoryName() : VGLogCategory(#CategoryName) {} \
    } CategoryName;

/** 
 * 定义日志类别的宏，通常与头文件中的DECLARE_LOG_CATEGORY_EXTERN配对使用。
 * @param CategoryName, 要定义的类别
 **/
#define DEFINE_LOG_CATEGORY(CategoryName) VGLogCategory##CategoryName CategoryName;

/** 
 * 将日志类别定义为C++ "static"的宏。这应该只在源文件中声明。只能在单个文件中访问。
 * @param CategoryName, 要声明的类别
 * @param DefaultVerbosity, 默认运行时详细程度
 * @param CompileTimeVerbosity, 编译到代码中的最大详细程度
 **/
#define DEFINE_LOG_CATEGORY_STATIC(CategoryName, DefaultVerbosity, CompileTimeVerbosity) \
    static struct VGLogCategory##CategoryName : public VGLogCategory<VGLogVerbosity::DefaultVerbosity, VGLogVerbosity::CompileTimeVerbosity> \
    { \
        VG_FORCE_INLINE VGLogCategory##CategoryName() : VGLogCategory(#CategoryName) {} \
    } CategoryName;

/** 编译时最小日志级别 */
#ifndef COMPILED_IN_MINIMUM_VERBOSITY
    #define COMPILED_IN_MINIMUM_VERBOSITY VGLogVerbosity::VeryVerbose
#endif

/**
 * 如果日志类别在请求的详细程度级别处于活动状态，则记录格式化消息的宏。
 *
 * @param CategoryName   DEFINE_LOG_CATEGORY提供的日志类别名称。
 * @param Verbosity      此消息的详细程度级别。参见VGLogVerbosity。
 * @param Format         printf样式的格式字符串字面量。
 */
#define VG_LOG(CategoryName, Verbosity, Format, ...) \
    VG_PRIVATE_LOG(VG_NOTHING, constexpr, CategoryName, Verbosity, Format, ##__VA_ARGS__)

/**
 * 如果日志类别在请求的详细程度级别处于活动状态，则有条件地记录格式化消息的宏。
 *
 * @note 除非日志类别在请求的详细程度级别处于活动状态，否则不会评估条件。
 *
 * @param Condition      必须评估为true才能记录消息的条件。
 * @param CategoryName   DEFINE_LOG_CATEGORY提供的日志类别名称。
 * @param Verbosity      此消息的详细程度级别。参见VGLogVerbosity。
 * @param Format         printf样式的格式字符串字面量。
 */
#define VG_CLOG(Condition, CategoryName, Verbosity, Format, ...) \
    VG_PRIVATE_LOG(if (Condition), constexpr, CategoryName, Verbosity, Format, ##__VA_ARGS__)

// 辅助宏定义
#define VG_NOTHING

/** 用于实现公共日志宏的私有宏。请勿直接调用！ */
#define VG_PRIVATE_LOG(Condition, CategoryConst, Category, Verbosity, Format, ...) \
{ \
    static_assert((VGLogVerbosity::Verbosity & VGLogVerbosity::VerbosityMask) < VGLogVerbosity::NumVerbosity && VGLogVerbosity::Verbosity > 0, "Verbosity must be constant and in range."); \
    if constexpr ((VGLogVerbosity::Verbosity & VGLogVerbosity::VerbosityMask) == VGLogVerbosity::Fatal) \
    { \
        Condition \
        { \
            VGLogOutput(Category.GetCategoryName(), VGLogVerbosity::Verbosity, Format, ##__VA_ARGS__); \
            std::abort(); \
        } \
    } \
    else if constexpr ((VGLogVerbosity::Verbosity & VGLogVerbosity::VerbosityMask) <= COMPILED_IN_MINIMUM_VERBOSITY) \
    { \
        if CategoryConst ((VGLogVerbosity::Verbosity & VGLogVerbosity::VerbosityMask) <= Category.GetCompileTimeVerbosity()) \
        { \
            if (!Category.IsSuppressed(VGLogVerbosity::Verbosity)) \
            { \
                Condition \
                { \
                    VGLogOutput(Category.GetCategoryName(), VGLogVerbosity::Verbosity, Format, ##__VA_ARGS__); \
                } \
            } \
        } \
    } \
}

/** 
 * 返回给定日志类别在给定详细程度级别是否处于活动状态（记录）的谓词
 * @param CategoryName 日志类别的名称
 * @param Verbosity, 要测试的详细程度级别
**/
#define VG_LOG_ACTIVE(CategoryName, Verbosity) \
    (((VGLogVerbosity::Verbosity & VGLogVerbosity::VerbosityMask) <= CategoryName.GetCompileTimeVerbosity()) && \
     !CategoryName.IsSuppressed(VGLogVerbosity::Verbosity))

// 调试日志宏（仅在Debug模式下有效）
#ifdef _DEBUG
    #define VG_DEBUG_LOG(Format, ...) VGLogOutput("Debug", VGLogVerbosity::Log, "[DEBUG] " Format, ##__VA_ARGS__)
#else
    #define VG_DEBUG_LOG(Format, ...)
#endif

// 预定义的常用日志类别
DECLARE_LOG_CATEGORY_EXTERN(LogTemp, Log, All)
DECLARE_LOG_CATEGORY_EXTERN(LogEngine, Log, All)
DECLARE_LOG_CATEGORY_EXTERN(LogEditor, Log, All)
DECLARE_LOG_CATEGORY_EXTERN(LogRender, Log, All)
DECLARE_LOG_CATEGORY_EXTERN(LogCore, Log, All)

/*----------------------------------------------------------------------------
    VGameEngine核心函数声明
----------------------------------------------------------------------------*/

// 前向声明VGameEngine核心类
class VGEngineLoop;
class VCommand;
